﻿using System;
using _5E.Infrastructure.Logging;
using StoneAge.Contract;
using StoneAge.DataContract.Messaging;
using StoneAge.Models.Repository;
using _5E.Infrastructure.Querying;
using StoneAge.Models.Entity;
using System.Collections.Generic;
using System.Linq;
using StoneAge.DataContract.View;
using StoneAge.DataContract.Extension;

namespace StoneAge.Service
{
    public class MapService : IMapService
    {
        private const Int32 MAX_DISTANCE = 18;
        private const Int32 AREA_COUNT = 9;
        private IMapRepository m_mapRepository = null;
        private IMapAreaRepository m_mapAreaRepository = null;
        private ICoordinateRepository m_coordinateRepository = null;
        private IRoleRepository m_roleRepository = null;

        public MapService(
            IMapRepository mapRepository,
            IMapAreaRepository mapAreaRepository,
            ICoordinateRepository coordinateRepository,
            IRoleRepository roleRepository)
        {
            m_mapRepository = mapRepository;
            m_mapAreaRepository = mapAreaRepository;
            m_coordinateRepository = coordinateRepository;
            m_roleRepository = roleRepository;
        }

        public GetMapResponse GetMapBy(GetMapRequest request)
        {
            GetMapResponse response = new GetMapResponse();
            try
            {
                Role role = m_roleRepository.FindBy(request.RoleId);
                Map map = m_mapRepository.FindBy(role.Coordinate.MapId);
                MapArea centerArea = map.Areas.First(
                    a => Math.Abs(a.CoordinateE - role.Coordinate.E) + Math.Abs(a.CoordinateS - role.Coordinate.S) < MAX_DISTANCE);
                IList<MapArea> areas = new List<MapArea>(AREA_COUNT);
                for (int y = centerArea.Y - 1; y <= centerArea.Y + 1; y++)
                {
                    for (int x = centerArea.X - 1; x <= centerArea.X + 1; x++)
                    {
                        areas.Add(map.Areas.FirstOrDefault(a => a.X == x && a.Y == y));
                    }
                }

                MapView view = map.ConvertToMapView();
                view.Srcs = areas.ConvertToSrc();
                Int32 s = role.Coordinate.S - centerArea.CoordinateS;
                Int32 e = role.Coordinate.E - centerArea.CoordinateE;
                view.X = (s + e) * 32;
                view.Y = (s - e) * 24;
                response.Map = view;
            }
            catch (Exception ex)
            {
                LoggingFactory.Logger.Log(ex);
                response.Success = false;
            }
            return response;
        }
    }
}
